/*
package com.ruoyi.runner;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.ObjectUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.order.domain.*;
import com.ruoyi.order.enums.NodeResultStatusEnum;
import com.ruoyi.order.enums.NodeTestResultEnum;
import com.ruoyi.order.event.ProcessDataEvent;
import com.ruoyi.order.proxy.factory.req.FactoryHeader;
import com.ruoyi.order.proxy.factory.req.ProcessDataRequest;
import com.ruoyi.order.service.*;
import com.ruoyi.order.station.cmd.DB5409;
import com.ruoyi.order.station.handle.StationExchangeService;
import com.ruoyi.order.station.operate.DB5850;
import com.ruoyi.order.station.operate.DB5850Value;
import com.ruoyi.order.station.request.*;
import com.ruoyi.order.station.response.DB5410Server;
import com.ruoyi.order.station.response.PassResponse;
import com.ruoyi.order.station.transform.DBTrans;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.websocket.WebSocketUsers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ScanPLCService {

    @Autowired
    private StationExchangeService stationExchangeService;
    @Autowired
    private IMesProdRecordService prodRecordService;
    @Autowired
    private IMesModelNodeRelaService mesModelNodeRelaService;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private IMesDetectNodeService detectNodeService;
    @Autowired
    private IMesProductNodeResultService productNodeResultService;

    private final ApplicationEventPublisher eventPublisher;
    private static Map<String, List<MesModelNodeRela>> partModelRelaMap = new HashMap<>();
    //手工站操作指引
    private static Set<String> operationNodeCodeSet = new HashSet<>();
    static {
        operationNodeCodeSet.add("7");
        operationNodeCodeSet.add("9");
        operationNodeCodeSet.add("11");
        operationNodeCodeSet.add("12");
        operationNodeCodeSet.add("19");
        operationNodeCodeSet.add("21");
        operationNodeCodeSet.add("23");
    }

    @Autowired
    private IMesStationOperateFlowService mesStationOperateFlowService;
    //操作指引列表
    private static Map<String, List<MesStationOperateFlow>> operateFlowMap = null;

    //上一次的操作指令DB块内容
    private static DB5850 dB5850Last = null;
    //上一次的操作指引数据
    private static String objectJson = null;


    public ScanPLCService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    public void plcRW(String lineNumber,String nodeCode) {
        if (lineNumber != null && lineNumber.equals("1")) {
            lineOne(lineNumber, nodeCode);
        }
    }

    private void lineOne(String lineNumber,String nodeCode) {
        log.info("组装线定时任务 lineNumber={},nodeCode={}", lineNumber, nodeCode);
        MesDetectNode mesDetectNode = new MesDetectNode();
        mesDetectNode.setSubsysCode(lineNumber);
        List<MesDetectNode> detectNodeList = detectNodeService.selectMesDetectNodeList(mesDetectNode);
        for (MesDetectNode detectNode : detectNodeList) {
            //单独测试nodeCode站位
            if (StringUtils.isNotEmpty(nodeCode)&&!detectNode.getNodeCode().equals(nodeCode)) {
                continue;
            }
            //读取DB5409
            DB5409 db5409 = stationExchangeService.getDB5409(detectNode);
            //首站处理
            if (detectNode.getSortIndex() == 1) {
                log.info("handleFirstStation is Start!");
                handleFirstStation(lineNumber, db5409, detectNode);
            } else if (detectNode.getSortIndex() > 1 && detectNode.getSortIndex() < detectNodeList.size()) {
                //执行中间过站
                handleMiddleStation(lineNumber, db5409, detectNode);
            } else if (detectNode.getSortIndex() == detectNodeList.size() && detectNode.getSortIndex() >= 1) {
                //执行尾站
                handleLastStation(lineNumber, db5409, detectNode);
                log.info("handleLastStation is End!");
            }
        }
    }

    */
/**
     * 扫描操作指引数据
     * @param detectNode
     *//*

    public void operateGuide(MesDetectNode detectNode) {

        //获取操作指令
        if(operationNodeCodeSet.contains(detectNode.getNodeCode())){
            if (detectNode.getNodeCode().equals("7")
            ||detectNode.getNodeCode().equals("9")
            ||detectNode.getNodeCode().equals("11")
            ||detectNode.getNodeCode().equals("12")
            ||detectNode.getNodeCode().equals("19")
            ||detectNode.getNodeCode().equals("21")
            ||detectNode.getNodeCode().equals("23")){
                log.info("detectNode.getNodeCode() = {}",detectNode.getNodeCode());
                //获取到加工操作数据指令
                DB5850 db5850 = stationExchangeService.getDB5850(detectNode);
                DB5850Value db5850Value = DBTrans.transformDB5850Value(db5850);

                if (detectNode.getNodeCode() != null && detectNode.getNodeCode().length()==1){
                    db5850Value.setStationCode("OP0"+ detectNode.getNodeCode());
                }else{
                    db5850Value.setStationCode("OP"+ detectNode.getNodeCode());
                }
                List<MesStationOperateFlow> operateFlowList = queryOperationFlowList(detectNode.getNodeCode());
                if (operateFlowList != null) {
                    operateFlowList.forEach(operateFlow -> {
                        if (operateFlow.getOperateCode().intValue() == db5850Value.getSequencer()){
                            db5850Value.setOperateDesc(operateFlow.getOperateCode().intValue()+":"+operateFlow.getDescription());
                            db5850Value.setOperateCode(operateFlow.getOperateCode());
                        }
                    });
                }
                //推送指令报文
                if(db5850Value!=null&& StringUtils.isNotEmpty(db5850Value.getPartIdentifier())){
                    long begin = System.currentTimeMillis();
                    WebSocketUsers.sendMessageToUserByStationCode(detectNode.getNodeCode(), "1|".concat(JSON.toJSONString(db5850Value)));
                    log.info("websocket推送 指令报文耗时：{}", System.currentTimeMillis()-begin);
                }
                //推送数据报文
                long begin = System.currentTimeMillis();
                Object obj = stationExchangeService.readOperationData(detectNode);
                log.info("读取操作指引报文耗时：{}", System.currentTimeMillis()-begin);
                String json = JSON.toJSONString(obj);
                log.info("包含解析成json总耗时：{}", System.currentTimeMillis()-begin);
                if(objectJson==null){
                    objectJson = json;
                    WebSocketUsers.sendMessageToUserByStationCode(detectNode.getNodeCode(), "2|".concat(json));
                }else if (json.equals(objectJson)){
                    WebSocketUsers.sendMessageToUserByStationCode(detectNode.getNodeCode(), "2|".concat(json));
                }

            }
        }
    }

    */
/**
     *
     * @param nodeCode
     * @return
     *//*

    public List<MesStationOperateFlow>  queryOperationFlowList(String nodeCode) {
        if (operateFlowMap==null){
            MesStationOperateFlow param = new MesStationOperateFlow();
            List<MesStationOperateFlow> operateFlowList = mesStationOperateFlowService.selectMesStationOperateFlowList(param);
            operateFlowMap = operateFlowList.stream().collect(
                    Collectors.groupingBy(MesStationOperateFlow::getNodeCode)
            );
            log.info("OperationRunner 操作流程初始化完成 operateFlowList.size = {}",operateFlowList.size());
        }
        return operateFlowMap.get(nodeCode);
    }

    public void handleNode(MesDetectNode detectNode,int nodeLengh){
        //读取DB5409
        DB5409 db5409 = stationExchangeService.getDB5409(detectNode);

        //首站处理
        if (detectNode.getSortIndex() == 1) {
            log.info("handleFirstStation is Start!");
            handleFirstStation("1", db5409, detectNode);
        } else if (detectNode.getSortIndex() > 1 && detectNode.getSortIndex() < nodeLengh) {
            //执行中间过站
            handleMiddleStation("1", db5409, detectNode);
        } else if (detectNode.getSortIndex() == nodeLengh && detectNode.getSortIndex() >= 1) {
            //执行尾站
            handleLastStation("1", db5409, detectNode);
            log.info("handleLastStation is End!");
        }
    }
    */
/**
     * 生产数据处理
     *
     * @param detectNode
     * @param isFirstStation 是否是首站
     *//*

    public boolean handleProductData(MesDetectNode detectNode, boolean isFirstStation) {
        //生产数据已生成
        //生产数据读取
        ProcessRequest processRequest = stationExchangeService.readProductHeader(detectNode, isFirstStation);
        String partNumber = "";
        try {
            partNumber = new String(processRequest.getPartIdentifier(), "UTF-8");
            partNumber = partNumber.trim();
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        //查询是否已做过数据
        MesProductNodeResult existResult = productNodeResultService.getByStationCodeAndPartNumber(detectNode.getNodeCode(), partNumber);
        if (existResult != null){
            return false;
        }
        MesProductNodeResult productNodeResult = new MesProductNodeResult();
        String testDetail = "";
        if (detectNode.getNodeCode().equals("1") || detectNode.getNodeCode().equals("9")
                || detectNode.getNodeCode().equals("12")
                || detectNode.getNodeCode().equals("17")
                || detectNode.getNodeCode().equals("19")
                || detectNode.getNodeCode().equals("21")) {
            Object object1 = stationExchangeService.readProductData(detectNode, isFirstStation);
            Object object2 = stationExchangeService.readProductDataExtended(detectNode);
            testDetail = ObjectUtils.mergeObj2JSONStr(object1, object2);
        } else {
            Object object = stationExchangeService.readProductData(detectNode, isFirstStation);
            testDetail = ObjectUtils.obj2JSONStr(object);
        }
        productNodeResult.setTestHeader(JSON.toJSONString(DBTrans.getProductHeader(processRequest)));
        productNodeResult.setTestDetail(testDetail);
        productNodeResult.setSubsysCode(detectNode.getSubsysCode());
        productNodeResult.setIp(detectNode.getIp());
        productNodeResult.setMachineModel(detectNode.getMachineModel());
        productNodeResult.setSortIndex(detectNode.getSortIndex());
        productNodeResult.setStationCode(detectNode.getNodeCode());
        productNodeResult.setStatus(NodeResultStatusEnum.VALID.getCode());
        productNodeResult.setPartNumber(partNumber);
        productNodeResult.setTestResult(String.valueOf(processRequest.getResult()));
        productNodeResultService.insertMesProductNodeResult(productNodeResult);
        //读生产数据完成后写入DB5439
        stationExchangeService.wirteProductDataResponse(DBTrans.getDB5439Server(processRequest), detectNode, isFirstStation);
        //发送事件，发送数据给工厂
        eventPublisher.publishEvent(new ProcessDataEvent(this, transformProcessData(processRequest, productNodeResult.getId(), testDetail)));
        return true;
    }

    */
/**
     * 转换成工厂数据格式
     *
     * @param processRequest
     * @param body
     * @return
     *//*

    public ProcessDataRequest transformProcessData(ProcessRequest processRequest, Long resultId, String body) {
        ProcessDataRequest processDataRequest = new ProcessDataRequest();
        FactoryHeader header = new FactoryHeader();
        header.setLineNo(processRequest.getLineNo());
        header.setResultId(resultId);
        if(processRequest.getStationNo()<10){
            header.setStationNo("OP0" + processRequest.getStationNo());
        }else {
            header.setStationNo("OP" + processRequest.getStationNo());
        }
        header.setStationIndex(processRequest.getStationindex());
        header.setWpcId(new String(processRequest.getWpcId()));
        header.setWpcId(StringUtils.trim(header.getWpcId()));
        header.setTypeNo(new String(processRequest.getTypeNo()));
        header.setTypeNo(StringUtils.trim(header.getTypeNo()));
        header.setPartIdentifier(new String(processRequest.getPartIdentifier()));
        header.setPartIdentifier(StringUtils.trim(header.getPartIdentifier()));
        header.setProductionTime(new String(processRequest.getProductionTime()));
        header.setProductionTime(StringUtils.trim(header.getProductionTime()));
        header.setResult(processRequest.getResult());
        header.setNoBits(processRequest.getNoBits());
        processDataRequest.setHeader(header);
        processDataRequest.setBody(body);
        return processDataRequest;
    }

    */
/**
     * 首站处理
     *
     * @param db5409
     * @param detectNode
     *//*

    public void handleFirstStation(String lineNumber, DB5409 db5409, MesDetectNode detectNode) {
        if (db5409.getT10Send() == 1) {
            //首站，1: PLC可以读DB5410 数据块
            DB5410PLC db5410PLC = stationExchangeService.getDB5410(detectNode);
            MesProdRecord mesProdRecord = new MesProdRecord();
            try {
                mesProdRecord.setModelCode(new String(db5410PLC.getRouteList(), "UTF-8"));
                mesProdRecord.setPartId(new String(db5410PLC.getPartIdentifier(), "UTF-8"));
                mesProdRecord.setPartId(StringUtils.trim(mesProdRecord.getPartId()));
                mesProdRecord.setModelCode(StringUtils.trim(mesProdRecord.getModelCode()));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
            //保存入库
            if (Objects.isNull(prodRecordService.getMesProdRecordByPartId(mesProdRecord.getPartId()))) {
                log.info("保存入库 mesProdRecord = {}", JSONObject.toJSONString(mesProdRecord));
                prodRecordService.insertMesProdRecord(mesProdRecord);
            }
            //获取产品所有必生产站位列表
            List<MesModelNodeRela> relaList = queryRelaListByPartId(lineNumber,mesProdRecord.getPartId());
            //写入DB5409
            log.info("写入DB5409");
            if (CollectionUtils.isNotEmpty(relaList)) {
                db5409.setT10Result(1);
            } else {
                db5409.setT10Result(2);
                log.error("db5410PLC.getRouteList()={},获取到的必过站位列表为空 ", db5410PLC.getRouteList());
            }
            //查询是否已做过数据,如果做过则给个异常3编码
            MesProductNodeResult existResult = productNodeResultService.getByStationCodeAndPartNumber(detectNode.getNodeCode(), mesProdRecord.getPartId());
            if (existResult != null){
                db5409.setT10Result(3);
            }
            stationExchangeService.writeDB5409(db5409, detectNode);
            //写入DB5410 Server
            log.info("写入DB5410 Server detectNode.getNodeCode() ={}", detectNode.getNodeCode());
            DB5410Server db5410Server = DBTrans.getDB5410Server(db5410PLC);
            stationExchangeService.wirteDB5410Server(db5410Server, detectNode);
        }
        //首站生产已完成，读取生产数据
        if (db5409.getT30SendFirst() == 1) {
            handleProductData(detectNode,true);
            db5409.setT30ResultFirst(1);
            stationExchangeService.writeDB5409(db5409, detectNode);
        }
    }

    */
/**
     * 中间站处理
     *
     * @param db5409
     * @param detectNode
     *//*

    public void handleMiddleStation(String lineNumber, DB5409 db5409, MesDetectNode detectNode) {
        //非首站，1: PLC已扫码partNumber，可以读DB5411数据块
        if (db5409.getT11Send() == 1) {
            passStation(lineNumber, db5409, detectNode);
        }
        //生产数据已完成，进行读取，并写入已完成读取标记
        if (db5409.getT30Send() == 1) {
            if (handleProductData(detectNode,false)){
                db5409.setT30Result(1);
                stationExchangeService.writeDB5409(db5409, detectNode);

            }
        }
    }

    */
/**
     * 尾站处理
     *
     * @param db5409
     * @param detectNode
     *//*

    public void handleLastStation(String lineNumber, DB5409 db5409, MesDetectNode detectNode) {
        //非首站，1: PLC已扫码partNumber，可以读DB5411数据块
        if (db5409.getT11Send() == 1) {
            passStation(lineNumber, db5409, detectNode);
        }
        //检测关键节点的QunlityGate信息
        if (db5409.getT16Send() == 1) {
            //所有节点生产信息获取
            DB5416PLC db5416PLC = stationExchangeService.getDB5416(detectNode);
        }
        //生产数据已完成，进行读取，并写入已完成读取标记
        if (db5409.getT30Send() == 1) {
            if (handleProductData(detectNode,false)){
                db5409.setT30Result(1);
                stationExchangeService.writeDB5409(db5409, detectNode);
            }
        }
        if (db5409.getT19Send() == 1){
            //产品下线，插入产品表
            DB5419PLC db5419PLC = stationExchangeService.getDB5419(detectNode);
            log.info("db5419PLC = {}", JSON.toJSONString(db5419PLC));
        }
    }

    */
/**
     * 过站处理,中间和尾站共用逻辑
     *
     * @param db5409
     * @param detectNode
     *//*

    public void passStation(String lineNumber, DB5409 db5409, MesDetectNode detectNode) {
        //当前站点是否生产标记
        boolean isProduce = false;
        //当前需要生产站位编码
        String currentStationCode = "";
        //必要生产站位编码列表
        List<String> needStationCodeList = new ArrayList<>();
        //已生产历史记录
        Map<String, String> produceRecordMap = new HashMap<>();
        String partId = "";
        PassRequest passRequest = stationExchangeService.getPassRequest(detectNode);
        try {
            partId = new String(passRequest.getPartIdentifier(), "UTF-8");
            partId = partId.trim();
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        if (StringUtils.isEmpty(partId)){
            log.error("产品ID为空，partId = {}",partId);
            return;
        }
        //获取产品所有必生产站位列表
        List<MesModelNodeRela> relaList = queryRelaListByPartId(lineNumber, partId);
        if(CollectionUtils.isEmpty(relaList)){
            log.error("没有找到大类对应生产节点关系 relaList = {}",relaList);
            return;
        }
        for (MesModelNodeRela rela : relaList) {
            if (rela.getStationCode().indexOf("_") > 0) {//25站位有两个，去掉下标索引，直接用25号站代替
                needStationCodeList.add(rela.getStationCode().split("_")[0]);
            } else {
                needStationCodeList.add(rela.getStationCode());
            }
        }
        //获取生产数据入库记录
        MesProductNodeResult param = new MesProductNodeResult();
        param.setSubsysCode(detectNode.getSubsysCode());
        param.setPartNumber(partId);
        param.setStatus(NodeResultStatusEnum.VALID.getCode());
        List<MesProductNodeResult> nodeResultList = productNodeResultService.selectMesProductNodeResultByPartNumber(param);
        if (CollectionUtils.isNotEmpty(nodeResultList)) {
            for (MesProductNodeResult result : nodeResultList) {
                if (result.getStationCode().indexOf("_") > 0) {//25站位有两个，去掉下标索引，直接用25号站代替
                    produceRecordMap.put(result.getStationCode().split("_")[0], result.getStationCode().split("_")[0]);
                } else {
                    produceRecordMap.put(result.getStationCode(), result.getStationCode());
                }
            }
        }
        //获取即将生成站位
        for (String stationCode : needStationCodeList) {
            if (!produceRecordMap.containsKey(stationCode)) {
                currentStationCode = stationCode;
                break;
            }
        }
        //如果循环必做站位是25_1,或者25_2,已经存在生产记录则不处理
        if (detectNode.getNodeCode().indexOf("_") >= 0
                && produceRecordMap.containsKey(detectNode.getNodeCode().split("_")[0])) {
            return;
        }
        if (currentStationCode.equals(detectNode.getNodeCode())
                && currentStationCode.equals(String.valueOf(passRequest.getStationNo()))) {
            isProduce = true;
        }
        //25站位处理
        if (detectNode.getNodeCode().indexOf("_")>= 0 && currentStationCode.equals(detectNode.getNodeCode().split("_")[0]) ){
            isProduce = true;
        }
        //尾站27站位处理
        if (currentStationCode.indexOf("L")>=0&&currentStationCode.equals(passRequest.getStationNo()+"L")){
            isProduce = true;
        }
        //写入过站结果
        PassResponse passResponse = new PassResponse();
        passResponse.setLineNo(passRequest.getLineNo());
        passResponse.setTelegramNo(passRequest.getTelegramNo());
        passResponse.setStationNo(passRequest.getStationNo());
        passResponse.setStationindex(passRequest.getStationindex());
        passResponse.setPartIdentifier(passRequest.getPartIdentifier());
        passResponse.setTypeNo(passRequest.getTypeNo());
        passResponse.setReturnCode(1);
        if (isProduce) {
            if (currentStationCode.indexOf("L")>=0){
                passResponse.setPartForStation(Integer.valueOf(currentStationCode.split("L")[0]));
            }else {
                passResponse.setPartForStation(Integer.valueOf(currentStationCode));
            }
        } else {
            if (currentStationCode.indexOf("L")>=0){
                passResponse.setNextForStation(Integer.valueOf(currentStationCode.split("L")[0]));
            }else {
                passResponse.setNextForStation(Integer.valueOf(currentStationCode));
            }
        }
        //存在NG产品记录
        if(judgeNGProduct(nodeResultList)){
            passResponse.setPartForStation(999);
        }
        //写入过站数据，DB511块
        stationExchangeService.writePassResponse(passResponse, detectNode);
        //写入指令数据
        db5409.setT11Result(1);
        stationExchangeService.writeDB5409(db5409, detectNode);
    }
    */
/**
     * 判断是否NG（不合格）产品生产记录
     *
     * @param nodeResultList
     * @return
     *//*

    public boolean judgeNGProduct(List<MesProductNodeResult> nodeResultList){
        AtomicBoolean result = new AtomicBoolean(false);
        if (CollectionUtils.isEmpty(nodeResultList)){
            return false;
        }
        nodeResultList.forEach(item->{
            if (NodeTestResultEnum.FAIL.getCode().equals(item.getTestResult())){
                result.set(true);
            }
        });
        return result.get();
    }

    */
/**
     * 根据partId查询产品大类对应检测站位列表
     *
     * @param partId
     * @return
     *//*

    public List<MesModelNodeRela> queryRelaListByPartId(String lineNumber, String partId) {
        if (partModelRelaMap.containsKey(partId+"_" +lineNumber)) {
            return partModelRelaMap.get(partId+"_" +lineNumber);
        }
        MesProdRecord mesProdRecord = prodRecordService.getMesProdRecordByPartId(partId);
        if (mesProdRecord == null){
            return null;
        }
        String modelCode = mesProdRecord.getModelCode();
        List<MesModelNodeRela> relaList = mesModelNodeRelaService.queryRelaListByModelCode(lineNumber, modelCode);
        partModelRelaMap.put(partId+"_" +lineNumber, relaList);
        return relaList;
    }
    */
/**
     * 生产下线去掉缓存
     *
     * @param partId
     *//*

    public void offLineByPartId(String partId) {
        partModelRelaMap.remove(partId);
    }
}
*/
